package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ListUtils;
import com.ruoyi.system.domain.SnUserLib;
import com.ruoyi.system.mapper.SnUserLibMapper;
import com.ruoyi.system.service.ISnUserLibService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 彩民抽奖信息库Service业务层处理
 *
 * @author ruoyi
 * @date 2022-12-26
 */
@Service
public class SnUserLibServiceImpl implements ISnUserLibService {


    private Logger LOGGER = LoggerFactory.getLogger(SnUserLibServiceImpl.class);

    @Autowired
    private SnUserLibMapper snUserLibMapper;

    /**
     * 查询彩民抽奖信息库
     *
     * @param id 彩民抽奖信息库主键
     * @return 彩民抽奖信息库
     */
    @Override
    public SnUserLib selectSnUserLibById(String id) {
        return snUserLibMapper.selectSnUserLibById(id);
    }

    /**
     * 查询彩民抽奖信息库列表
     *
     * @param snUserLib 彩民抽奖信息库
     * @return 彩民抽奖信息库
     */
    @Override
    public List<SnUserLib> selectSnUserLibList(SnUserLib snUserLib) {
        return snUserLibMapper.selectSnUserLibList(snUserLib);
    }

    /**
     * 新增彩民抽奖信息库
     *
     * @param snUserLib 彩民抽奖信息库
     * @return 结果
     */
    @Override
    public int insertSnUserLib(SnUserLib snUserLib) {
        return snUserLibMapper.insertSnUserLib(snUserLib);
    }

    /**
     * 修改彩民抽奖信息库
     *
     * @param snUserLib 彩民抽奖信息库
     * @return 结果
     */
    @Override
    public int updateSnUserLib(SnUserLib snUserLib) {
        return snUserLibMapper.updateSnUserLib(snUserLib);
    }

    /**
     * 批量删除彩民抽奖信息库
     *
     * @param ids 需要删除的彩民抽奖信息库主键
     * @return 结果
     */
    @Override
    public int deleteSnUserLibByIds(String ids) {
        return snUserLibMapper.deleteSnUserLibByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除彩民抽奖信息库信息
     *
     * @param id 彩民抽奖信息库主键
     * @return 结果
     */
    @Override
    public int deleteSnUserLibById(String id) {
        return snUserLibMapper.deleteSnUserLibById(id);
    }

    /**
     * 清空彩民抽奖信息库信息
     *
     * @return
     */
    @Override
    public int deleteSnUserLib() {
        return snUserLibMapper.deleteSnUserLib();
    }

    /**
     * 当前已经抽奖数量
     *
     * @return
     */
    @Override
    public int getCurrentLucky() {
        return snUserLibMapper.getCurrentLucky();
    }

    /**
     * 获取彩民总数量(去重)
     *
     * @param snUserLib
     * @return
     */
    @Override
    public int distantSnUserLibCount(SnUserLib snUserLib) {
        return snUserLibMapper.distantSnUserLibCount(snUserLib);
    }

    /**
     * 获取彩民总数量
     *
     * @param snUserLib
     * @return
     */
    @Override
    public int selectSnUserLibCount(SnUserLib snUserLib) {
        return snUserLibMapper.selectSnUserLibCount(snUserLib);
    }

    /**
     * 批量保存彩民信息
     *
     * @param snUserLibs
     * @return
     */
    @Override
    public int batchSaveSnUserLib(List<SnUserLib> snUserLibs) throws RuntimeException {
        try {
            long start = System.currentTimeMillis();
            //以2000为基准，拆分大数据量彩民集合，分成N个小数据量集合
            List<List<SnUserLib>> splitLists = ListUtils.batchList(snUserLibs, 2000);
            //启动N个任务线程
            int threadCount = splitLists.size();
            //创建线程池
            ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
            //任务执行结果集合，记录各子线程的执行结果
            List<CompletableFuture<Integer>> taskList = new ArrayList<>();
            for (List<SnUserLib> subList : splitLists) {
                //开启异步任务
                CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
                    int res = snUserLibMapper.batchSaveSnUserLib(subList);
                    LOGGER.info("彩民信息导入:任务执行数" + res);
                    return res;
                }, executorService);
                taskList.add(task);
            }
            //任务组合，等待各子任务都执行完成，汇总执行结果
            CompletableFuture.allOf(taskList.toArray(new CompletableFuture[0])).join();
            List<Integer> allResult = new ArrayList<>();
            taskList.stream().forEach($ -> {
                try {
                    //这个task的get()这里是直接返回，因为上面的join已经保证任务已经结束；如果任务没结束，这个get()会等到结束才返回值
                    allResult.add($.get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            int total = allResult.stream().mapToInt(Integer::intValue).sum();
            long end = System.currentTimeMillis();
            LOGGER.info("彩民信息导入:总记录数[" + snUserLibs.size() + "],拆分成[" + threadCount + "]个子任务进行保存,保存成功数[" + total + "],总耗时[" + (end - start) + "]ms");
            return total;
        } catch (Exception ex) {
            throw new RuntimeException(ex.toString());
        }
    }

    /**
     * 判断当前彩民是否已经中奖
     *
     * @param snUserLib
     * @return
     */
    @Override
    public int isLuckyUser(SnUserLib snUserLib) {
        return snUserLibMapper.isLuckyUser(snUserLib);
    }

    /**
     * 当前已经中奖的彩民
     *
     * @return
     */
    @Override
    public List<SnUserLib> getCurrentLuckyUsers() {
        return snUserLibMapper.getCurrentLuckyUsers();
    }

    /**
     * 随机获取1个用户
     *
     * @param snUserLib
     * @return
     */
    @Override
    public SnUserLib randomOneSnUserLib(SnUserLib snUserLib) {
        return snUserLibMapper.randomOneSnUserLib(snUserLib);
    }
}
